﻿// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// 
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
// 
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

namespace Neto.Json;

/// <summary>
///     Newtonsoft.Json 扩展
/// </summary>
public static class NewtonsoftJsonExtension
{
    /// <summary>
    ///     默认 Newtonsoft.Json 配置
    /// </summary>
    /// <returns></returns>
    public static JsonSerializerSettings GetSerializeObjectOption(bool isLongToString = false,
        bool initialLowercase = false)
    {
        var options = new JsonSerializerSettings
        {
            //WriteIndented = true,   // 缩进
            //Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,  // 中文乱码
            //PropertyNameCaseInsensitive = true  // 忽略大小写
            ReferenceLoopHandling =
                ReferenceLoopHandling.Ignore, //指定如何处理循环引用，None--不序列化，Error-抛出异常，Serialize--仍要序列化
            //MissingMemberHandling = MissingMemberHandling.Ignore,//控制在反序列化期间如何处理缺少的成员（例如JSON包含对象上不是成员的属性）。 Ignore 忽略，error 报错
            //ContractResolver = new CamelCasePropertyNamesContractResolver(),
            //Formatting = Formatting.Indented,//格式化 缩进
            MaxDepth = 10, //设置序列化的最大层数
            //NullValueHandling = NullValueHandling.Ignore,//空值处理
            //日期类型默认格式化处理
            // DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat,
            //DateParseHandling = Newtonsoft.Json.DateParseHandling.None,
            //DateFormatString = "yyyy-MM-dd'T'HH:mm:ss",
            //DateTimeZoneHandling = DateTimeZoneHandling.Local,

            //DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat,
            DateFormatString = "yyyy-MM-dd HH:mm:ss",
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            ContractResolver = new DefaultContractResolver() //json字符串大小写原样输出
        };
        //setting.Converters.AddLongTypeConverters();//long类型转换为字符串
        //setting.Converters.Add(new IsoDateTimeConverter
        //{
        //    DateTimeStyles = DateTimeStyles.AssumeUniversal
        //});//解决数据为 0001-01-01 00:00:00 的情形下 反序列化为 DateTimeOffset 格式报错问题,序列化时间的格式会变为 ：2022-10-01T10:00:00Z

        options.Converters.Add(new NewtonsoftJsonDateTimeOffsetConverter());

        if (isLongToString) options.Converters.AddLongTypeConverters(); //long类型转换为字符串,按需使用
        if (initialLowercase)
            //修改属性名称的序列化方式，首字母小写
            options.ContractResolver = new CamelCasePropertyNamesContractResolver();
        else
            options.ContractResolver = new DefaultContractResolver(); //json字符串大小写原样输出

        return options;
    }

    /// <summary>
    ///     默认 Newtonsoft.Json 配置
    /// </summary>
    /// <returns></returns>
    public static JsonSerializerSettings GetDeserializeObjectOption()
    {
        var options = new JsonSerializerSettings
        {
            //WriteIndented = true,   // 缩进
            //Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,  // 中文乱码
            //PropertyNameCaseInsensitive = true  // 忽略大小写
            ReferenceLoopHandling =
                ReferenceLoopHandling.Ignore, //指定如何处理循环引用，None--不序列化，Error-抛出异常，Serialize--仍要序列化
            //MissingMemberHandling = MissingMemberHandling.Ignore,//控制在反序列化期间如何处理缺少的成员（例如JSON包含对象上不是成员的属性）。 Ignore 忽略，error 报错
            //ContractResolver = new CamelCasePropertyNamesContractResolver(),
            //Formatting = Formatting.Indented,//格式化 缩进
            //MaxDepth = 10, //设置序列化的最大层数
            //NullValueHandling = NullValueHandling.Ignore,//空值处理
            //日期类型默认格式化处理
            // DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat,
            //DateParseHandling = Newtonsoft.Json.DateParseHandling.None,
            //DateFormatString = "yyyy-MM-dd'T'HH:mm:ss",
            //DateTimeZoneHandling = DateTimeZoneHandling.Local,

            //DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat,
            DateFormatString = "yyyy-MM-dd HH:mm:ss",
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            ContractResolver = new CamelCasePropertyNamesContractResolver() //json字符串大小写原样输出
        };
        //setting.Converters.AddLongTypeConverters();//long类型转换为字符串
        //setting.Converters.Add(new IsoDateTimeConverter
        //{
        //    DateTimeStyles = DateTimeStyles.AssumeUniversal
        //});//解决数据为 0001-01-01 00:00:00 的情形下 反序列化为 DateTimeOffset 格式报错问题,序列化时间的格式会变为 ：2022-10-01T10:00:00Z

        options.Converters.Add(new NewtonsoftJsonDateTimeOffsetConverter());

        return options;
    }

    /// <summary>
    ///     序列化为Json字符串（Newtonsoft.Json）
    /// </summary>
    /// <typeparam name="T">对象</typeparam>
    /// <param name="obj">序列化的对象</param>
    /// <param name="option"></param>
    /// <returns></returns>
    public static string ToJson2<T>(this T obj, JsonSerializerSettings option = null)
    {
        try
        {
            if (option == null) option = GetSerializeObjectOption();
            var result = JsonConvert.SerializeObject(obj, option);
            return result;
        }
        catch (Exception ex)
        {
            LogX.Error($"type:{typeof(T).FullName}\r\n{ex.ToStringEx()}", "Sys\\Error");
            return "";
        }
    }

    /// <summary>
    ///     反序列化为对象（Newtonsoft.Json）
    /// </summary>
    /// <typeparam name="T">对象</typeparam>
    /// <param name="jsonStr">json字符串</param>
    /// <param name="option"></param>
    /// <returns></returns>
    public static T? ToObj2<T>(this string? jsonStr, JsonSerializerSettings option = null)
    {
        try
        {
            if (string.IsNullOrWhiteSpace(jsonStr)) return default;
            if (option == null) option = GetDeserializeObjectOption();
            return JsonConvert.DeserializeObject<T>(jsonStr, option);
        }
        catch (Exception ex)
        {
            LogX.Error($"str:{jsonStr}\r\ntype:{typeof(T).FullName}\r\n{ex.ToStringEx()}", "Sys\\Error");
            return default;
        }
    }

    /// <summary>
    ///     设置 newtongsoftjson mvc选项配置
    /// </summary>
    /// <param name="mvcBuilder"></param>
    /// <param name="isLongToString"></param>
    /// <param name="initialLowercase">首字母小写，默认false</param>
    /// <returns></returns>
    public static IMvcBuilder AddAbcNewtonsoftJson(this IMvcBuilder mvcBuilder, bool isLongToString = false,
        bool initialLowercase = false)
    {
        mvcBuilder.AddNewtonsoftJson(options =>
        {
            if (isLongToString) options.SerializerSettings.Converters.AddLongTypeConverters(); //long类型转换为字符串,按需使用
            if (initialLowercase)
                //修改属性名称的序列化方式，首字母小写
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            else
                options.SerializerSettings.ContractResolver = new DefaultContractResolver(); //json字符串大小写原样输出

            options.SerializerSettings.ReferenceLoopHandling =
                ReferenceLoopHandling.Ignore; //指定如何处理循环引用，None--不序列化，Error-抛出异常，Serialize--仍要序列化
            //options.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore;//控制在反序列化期间如何处理缺少的成员（例如JSON包含对象上不是成员的属性）。 Ignore 忽略，error 报错
            //ContractResolver = new CamelCasePropertyNamesContractResolver(),
            //options.SerializerSettings.Formatting = Formatting.Indented;//格式化 缩进
            //options.SerializerSettings.MaxDepth = 10; //设置序列化的最大层数
            //options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;//空值处理
            //日期类型默认格式化处理
            //options.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;

            options.SerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
            options.SerializerSettings.DateParseHandling = DateParseHandling.None;
            //options.SerializerSettings.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal });//解决数据为 0001-01-01 00:00:00 的情形下 反序列化为 DateTimeOffset 格式报错问题

            options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";

            options.SerializerSettings.Converters.Add(new NewtonsoftJsonDateTimeOffsetConverter());
        });
        return mvcBuilder;
    }

    /// <summary>
    ///     JSON 字符串格式化
    /// </summary>
    /// <param name="str">输入的JSON字符串</param>
    /// <returns>格式化后的JSON字符串</returns>
    public static string JsonFormat(this string str)
    {
        try
        {
            var serializer = new JsonSerializer();
            TextReader tr = new StringReader(str);
            using (var jtr = new JsonTextReader(tr))
            {
                var obj = serializer.Deserialize(jtr);
                if (obj != null)
                {
                    var textWriter = new StringWriter();
                    var jsonWriter = new JsonTextWriter(textWriter)
                    {
                        Formatting = Formatting.Indented, Indentation = 4, IndentChar = ' '
                    };
                    serializer.Serialize(jsonWriter, obj);
                    return textWriter.ToString();
                }

                return str;
            }
        }
        catch (Exception)
        {
            return str;
        }
    }
}